﻿/*********************************************************************
 * Nombre: Parser.cs
 * Descripción: Clase encargada de parsear la página que se pasa.
 * Autor: DRD
 * Modificaciones:
 * ******************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BXPI
{
    public class Parser
    {
        private string pagina;
        private string paginaPlana;
        private string paginaPlanaMins;
        public struct parametro
        {
            public string identificador;
            public bool usar;
            public string tipo;
            public string nombre;
            public string id;
            public string valor;
            public bool inyectable;
        }

        public struct formulario
        {
            public bool usuario;
            public string nombre;
            public string accion;
            public string codigo;
            public List<parametro> botones;
            public List<parametro> parametros;
        }

        private string cadenaDis;
        private string tipoInyec;

        List<formulario> ListaFormularios = new List<formulario>();
        List<parametro> ListaParametros = new List<parametro>();
        int totalParametros = 0;

        private string caracteres = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
        private Boolean reducirCharset = true;
        private Boolean aprenderRepetidas = true;

        public Parser(string pagina)
        {
            this.pagina = pagina;
            paginaPlana = pagina.Replace(" ", "");
            paginaPlana = paginaPlana.Replace("\t", "");
            paginaPlana = paginaPlana.Replace("\n", "");
            paginaPlanaMins = paginaPlana.ToLower();
            SacarFormularios();
        }

        /// <summary>
        /// Busca en el código HTML el número de formularios
        /// </summary>
        /// <returns></returns>
        public int SacarFormularios() {
            formulario form;
            int indice = 0;
            int NumForms = 0;
            while (indice != -1){
                indice = paginaPlanaMins.IndexOf("<form", indice + 1);
                if (indice > 0) { 
                    NumForms++;
                    form.usuario = false;
                    form.nombre = ObtenerNombre(indice, paginaPlanaMins.IndexOf(">", indice + 1), "name=\"", paginaPlana);
                    form.accion = ObtenerNombre(indice, paginaPlanaMins.IndexOf(">", indice + 1), "action=\"", paginaPlana);
                    form.codigo = paginaPlana.Substring(indice, paginaPlana.IndexOf("</form>", indice + 1)+6 - indice + 1);
                    SacarListaParametros(form.codigo);
                    form.parametros = ListaParametros;
                    SacarListaBotones(form.codigo);
                    form.botones = ListaParametros;
                    ListaFormularios.Add(form);
                }
            }
            return NumForms;
        }

        /// <summary>
        /// Busca en cada formulario los inputs y crea una lista
        /// </summary>
        /// <param name="strFormulario"></param>
        /// <returns></returns>
        public int SacarListaParametros(string strFormulario)
        {
            ListaParametros = new List<parametro>();
            parametro param;
            int indice = 0;
            int posFin = 0;
            int NumParametros = 0;
            while (indice != -1)
            {
                indice = strFormulario.ToLower().IndexOf("<input", indice + 1);
                if (indice > 0)
                {
                    NumParametros++;
                    totalParametros++;
                    posFin = strFormulario.IndexOf("/>", indice + 1);
                    if (posFin == -1) {
                        posFin = strFormulario.IndexOf(">", indice + 1);
                    }
                    param.identificador = "p" + totalParametros;
                    param.usar = false;
                    param.tipo = ObtenerNombre(indice, posFin, "type=\"", strFormulario);
                    if (param.tipo == "") param.tipo = ObtenerNombre(indice, posFin, "type='", strFormulario);
                    param.nombre = ObtenerNombre(indice, posFin, "name=\"", strFormulario);
                    if (param.nombre == "") param.nombre = ObtenerNombre(indice, posFin, "name='", strFormulario);
                    param.id = ObtenerNombre(indice, posFin, "id=\"", strFormulario);
                    if (param.id == "") param.id = ObtenerNombre(indice, posFin, "id='", strFormulario);
                    if (param.nombre == "") param.nombre = param.id;
                    param.valor = ObtenerNombre(indice, posFin, "value=\"", strFormulario);
                    if (param.valor == "") param.valor = ObtenerNombre(indice, posFin, "value='", strFormulario);
                    param.inyectable = false;
                    ListaParametros.Add(param);
                }
            }
            return NumParametros;
        }

        /// <summary>
        /// Crea una lista de botones de cada formulario
        /// </summary>
        /// <param name="strFormulario"></param>
        /// <returns></returns>
        private int SacarListaBotones(string strFormulario)
        {
            ListaParametros = new List<parametro>();
            parametro boton;
            int indice = 0;
            int NumParametros = 0;
            while (indice != -1)
            {
                indice = strFormulario.ToLower().IndexOf("<button", indice + 1);
                if (indice > 0)
                {
                    NumParametros++;
                    totalParametros ++;
                    boton.identificador = "b" + totalParametros;
                    boton.usar = false;
                    boton.tipo = ObtenerNombre(indice, strFormulario.IndexOf(">", indice + 1), "type=\"", strFormulario);
                    boton.nombre = ObtenerNombre(indice, strFormulario.IndexOf(">", indice + 1), "name=\"", strFormulario);
                    boton.id = ObtenerNombre(indice, strFormulario.IndexOf(">", indice + 1), "id=\"", strFormulario);
                    boton.valor = ObtenerNombre(indice, strFormulario.IndexOf(">", indice + 1), "value=\"", strFormulario);
                    boton.inyectable = false;
                    ListaParametros.Add(boton);
                }
            }
            //BEGIN DRD 14/04/2009 Sacar elementos __DoPostBack
            indice = 0;
            while (indice != -1)
            {
                indice = strFormulario.ToLower().IndexOf("__dopostback('", indice + 1);
                if (indice > 0)
                {
                    NumParametros++;
                    totalParametros++;
                    boton.identificador = "b" + totalParametros;
                    boton.usar = false;
                    boton.tipo = "button";
                    boton.nombre = "__EVENTTARGET";
                    boton.id = "__EVENTTARGET";
                    boton.valor = ObtenerNombre(indice, strFormulario.IndexOf(")", indice + 1), "__dopostback('", strFormulario);
                    boton.inyectable = false;
                    ListaParametros.Add(boton);
                }
            }
            //END DRD 14/04/2009
            return NumParametros;
        }

        /// <summary>
        /// Obtiene el nombre de un campo del html
        /// </summary>
        /// <param name="posIni"></param>
        /// <param name="posFin"></param>
        /// <param name="campo"></param>
        /// <param name="texto"></param>
        /// <returns></returns>
        private string ObtenerNombre(int posIni, int posFin, string campo, string texto) {
            string resultado = "";
            string cadena = texto.Substring(posIni, posFin - posIni + 1); 
            if (cadena.ToLower().IndexOf(campo) != -1 )
            {
                int posicionI = cadena.ToLower().IndexOf(campo) + campo.Length;
                int posicionF = cadena.ToLower().IndexOf(campo.Substring(campo.Length-1, 1), posicionI);
                resultado = cadena.Substring(posicionI, posicionF - posicionI);
            }
            else 
            {
                resultado = "";
            }
            return resultado;
        }

        /// <summary>
        /// Añade los parámetros de usuario a la lista de parámetros
        /// </summary>
        /// <param name="nombre"></param>
        /// <param name="valor"></param>
        /// <param name="identificador"></param>
        public void anadirParametroUsuario(string nombre, string valor, string identificador){
            ListaParametros = new List<parametro>();
            parametro param;
            param.nombre = nombre;
            param.valor = valor;
            param.identificador = identificador;
            param.id = nombre;
            param.tipo="user";
            param.usar=false;
            param.inyectable=false;
           
            ListaParametros.Add(param);
            formulario formUser;
            formUser.usuario = true;
            formUser.accion = "";
            formUser.botones = new List<parametro>();
            formUser.codigo = "";
            formUser.nombre = "Formulario de Usuario";
            formUser.parametros = new List<parametro>();

            if (buscarFormUser()) //Significa que ya se ha insertado un parametro de usuario
            {
                ListaFormularios[posFormUserNombre()].parametros.Add(param);
            }
            else {
                formUser.parametros = ListaParametros;
                ListaFormularios.Add(formUser);
            
            }


        }

        /// <summary>
        /// Modifica los parámetros modificados por el usuario
        /// </summary>
        /// <param name="identificador"></param>
        /// <param name="usar"></param>
        /// <param name="nombre"></param>
        /// <param name="valor"></param>
        /// <param name="inyectable"></param>
        public void ModificarParametrosUser(string identificador, bool usar, string nombre, string valor, bool inyectable) {
            parametro param = new parametro();
            for (int i = 0; i< ListaFormularios.Count; i++){
                for (int j = 0; j < ListaFormularios[i].parametros.Count; j++ )
                {
                    if (ListaFormularios[i].parametros[j].identificador == identificador)
                    {
                        param = ListaFormularios[i].parametros[j];
                        param.usar = usar;
                        param.nombre = nombre;
                        param.valor = valor;
                        param.inyectable = inyectable;
                        ListaFormularios[i].parametros[j] = param;

                    }
                }
                for (int j = 0; j < ListaFormularios[i].botones.Count; j++)
                {
                    if (ListaFormularios[i].botones[j].identificador == identificador)
                    {
                        param = ListaFormularios[i].botones[j];
                        param.usar = usar;
                        param.nombre = nombre;
                        param.valor = valor;
                        param.inyectable = inyectable;
                        ListaFormularios[i].botones[j] = param;

                    }
                }
            }

        
        }

        /// <summary>
        /// Busca si existen parámetros creados por el usuarop
        /// </summary>
        /// <returns></returns>
        private bool buscarFormUser()
        {
            for (int i = 0; i< ListaFormularios.Count(); i++)
            {
                if (ListaFormularios[i].usuario == true) {
                    return true;
                }
            }
            return false;
        }


        private int posFormUserNombre()
        {
            for (int i = 0; i < ListaFormularios.Count(); i++)
            {
                if (ListaFormularios[i].usuario == true)
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public List<formulario> getListaDeFormularios() {
            return ListaFormularios;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ListaMod"></param>
        public void setListaDeFormularios(List<formulario> ListaMod)
        {
            ListaFormularios=ListaMod;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cadena"></param>
        /// <param name="tipo_inyec"></param>
        public void setParams(string cadena, string tipo_inyec) {
            cadenaDis = cadena;
            tipoInyec = tipo_inyec;
        }

        /// <summary>
        /// Devuelve la cadena discriminatoria
        /// </summary>
        /// <returns></returns>
        public string getCadenaDis()
        {
            return cadenaDis;
        }

        /// <summary>
        /// Devuelve el tipo de inyección que se va a realizar
        /// </summary>
        /// <returns></returns>
        public string getTipoInyec()
        {
            return tipoInyec;
        }

        /// <summary>
        /// Fija los valores de la inyección
        /// </summary>
        /// <param name="charset"></param>
        /// <param name="aprender"></param>
        /// <param name="reducir"></param>
        public void setConfigCharset(string charset, Boolean aprender, Boolean reducir)
        {
            caracteres = charset;
            aprenderRepetidas = aprender;
            reducirCharset = reducir;
        }

        /// <summary>
        /// Fija las opciones de la inyección
        /// </summary>
        /// <returns></returns>
        public ConfigurarCharset.configCharset getConfigCharset() {
            ConfigurarCharset.configCharset charset;
            charset.charset = caracteres;
            charset.aprenderPalabras = aprenderRepetidas;
            charset.reducirCharset = reducirCharset;
            return charset;
        }
    }
}
